package com.ql.reflect;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

public class ReflectTest {
	public static void main(String[] args) throws Exception{

		Class clazz=void.class;
		String str1="abc";
		
		Class cls=str1.getClass();
		Class cls1=String.class;
		Class cls2=Class.forName("java.lang.String");
		
		System.out.println(cls==cls1);
		System.out.println(cls1==cls2);
		
		//字节码是否是 基本数据类型
		System.out.println(cls.getName());  //获取 class的 名字
		System.out.println(cls.isPrimitive());
		System.out.println(int.class.isPrimitive());
		System.out.println(int.class==Integer.class);

		//获取Integer的基本类型
		System.out.println(Integer.TYPE==int.class);  
		//判断数组是不是基本数据类型
		System.out.println(int[].class.isPrimitive());
		//判断class 是不是 数组类型
		System.out.println(int[].class.isArray());
		
		//反射调用构造函数
		getConstructor();
		
		//使用 反射创建对象
		newInstance();
		
		//反射获取 字段
		reflectGetField();
		
		//反射 获取方法 并调用方法
		reflectInvoke(str1);
		
		//调用main方法
		TestArgusments.main(new String[]{"sdf","sdf","sdf"});
		
		//使用反射调用main方法
		String  className=args[0];
		Method mainMethod=Class.forName(className).getMethod("main", String[].class);
		mainMethod.invoke(null, (Object)new String[]{"aaa","bbb","ccc"});  //由于 jdk1.5  要兼容 1.4  所以就采用jdk1.4 的方式(1.4进行拆包)
		
		//数组的反射
		reflectArray();
	}
	
	//获取 Class 的构造方法
	public static void getConstructor() throws Exception{
		Constructor [] constructors=String.class.getConstructors();
		System.out.println("length:"+constructors.length+"\ndetail:"+Arrays.toString(constructors));
		
		//使用反射 调用构造方法 实现 创建对象 
		//new String(new StringBuffer("abc"));
		Constructor constructor=String.class.getConstructor(int[].class,int.class,int.class);
		constructor=String.class.getConstructor(StringBuffer.class);
		String str2=(String) constructor.newInstance(new StringBuffer("abc"));
		System.out.println(str2.charAt(2));
	}
	//Class 的 newInstance 省略了 构造函数的 newInstance 步骤
	public static void newInstance() throws Exception{
		String str1=(String)Class.forName("java.lang.String").newInstance();
		System.out.println(str1);
	}
	
	
	public static void reflectGetField() throws Exception{
		Class clazz=Class.forName("reflect.ReflectPoint");
		
		Constructor<ReflectPoint> cons=clazz.getConstructor(int.class,int.class);
		ReflectPoint rfp=rfp=(ReflectPoint)clazz.newInstance();  //声明的类必须要有 无参构造方法 
		System.out.println(rfp.y);
		rfp=cons.newInstance(3,5);
		System.out.println(rfp.y);
		
		Field [] fields=clazz.getFields();  //只能获取 非私有字段 
		System.out.println(Arrays.toString(fields));  //只能 处理 私有的字段  其他都能获取
		
		fields=clazz.getDeclaredFields();  //获取所有 声明的字段
		System.out.println(Arrays.toString(fields));  //只能 处理 私有的字段  其他都能获取
		
		Field fy=rfp.getClass().getField("y");
		System.out.println(fy.get(rfp));  //从某个对象中获取  字段的值
		System.out.println(Modifier.toString(fy.getModifiers()));  //获取修饰符
		System.out.println(fy.getType());  //获取字段类型
		
		//获取私有字段
		Field fx=rfp.getClass().getDeclaredField("x");  //
		fx.setAccessible(true);// 暴力访问 
		System.out.println(fx.get(rfp));
		
		reflectReplace(rfp);
		System.out.println(rfp);
		
		
	}
	
	public static void reflectReplace(Object obj) throws Exception{
		
		Field[] fields=obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			//字节码 用 ==进行比较 
			if(field.getType()==String.class){  
				if(field.getModifiers()==Modifier.PRIVATE){
					field.setAccessible(true);
					System.out.println("accessible");
				}
				String oldVal=(String)field.get(obj);
				String newVal=oldVal.replace('b', 'a');
				field.set(obj, newVal);
			}
			
		}
	}
	
	public static void reflectInvoke(String str) throws Exception{
		Method methodCharAt=str.getClass().getMethod("charAt", int.class);
		System.out.println(methodCharAt.invoke(str, 1));
		
		methodCharAt.invoke(str, 1);  //改方法 是静态 方法 ,不需要对象 
	}
	
	
	public static void reflectArray(){
		int[] a1=new int[]{1,2,3};
		int[] a2=new int[]{1,2,3,4};
		int[][] a3=new int[2][3];
		
		String [] a4=new String[]{"a","b","c"};
		
		System.out.println(a1.getClass()==a2.getClass());
		//System.out.println(a1.getClass()==a4.getClass());
		//System.out.println(a1.getClass()==a3.getClass());
		System.out.println(a1.getClass().getName());
		System.out.println(a1.getClass().getSuperclass().getName());
		System.out.println(a3.getClass().getName());
		System.out.println(a3.getClass().getSuperclass().getName());
		System.out.println(a4.getClass().getSuperclass().getName());
		System.out.println(a4.getClass().getName());
		
		Object aobj=a1;
		Object bobj=a3;
	//	Object[] aobj1=a1;
		Object obj5=a4;
		System.out.println("=================");
		System.out.println(Arrays.asList(a1));
		System.out.println(Arrays.asList(a4));
		
		//使用反射开始
		printObj("xyz");
		printObj(a4);
		HashSetAndArryList();
	}
	
	//hashCode  
	public static void HashSetAndArryList(){
		Collection collections=new ArrayList();
		ReflectPoint pt1=new ReflectPoint(2,2);
		ReflectPoint pt2=new ReflectPoint(5,5);
		ReflectPoint pt3=new ReflectPoint(2,2);
		
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);
		collections.add(pt1);
		System.out.println(collections.size());
		
		collections=new HashSet();
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);
		collections.add(pt1);
		System.out.println(collections.size());
		pt1.y=3;
		collections.remove(pt1);  //没有删除掉. 会内存溢出了
		System.out.println(collections.size());
		
	}
	
	
	public static void printObj(Object obj){
		Class clazz=obj.getClass();
		
		if(clazz.isArray()){
			int len=Array.getLength(obj);
			for(int i=0;i<len;i++){
				System.out.println(Array.get(obj, i));
			}
		}else{
			System.out.println(obj);
		}
		
		
	}
}

class TestArgusments{
	
	public static void main(String[]args){
		for (String arg : args) {
			System.out.println(arg);
		}
	}
	
}
